// Lindsay Gilmour
// Adam Lusch
// Dan Niceswanger
//
// Computer Graphics Project 1:
// Asteroids!
// A Tribute

#include "Ship.h"

const float32 Ship::MAX_SPEED = 30.0;

Ship::Ship(b2World* w)
	: Thing(w, 2, MAGIC_NUMBER)
{
	thrusting = false;
	
	genLists();
	
	float32 x = 0;
	float32 y = 0;
	
	b2BodyDef bodyDef;
	bodyDef.position.Set(x, y);
	body = world->CreateBody(&bodyDef);

	b2PolygonDef hull;
	hull.vertices[0] = b2Vec2(0, 1.5);
	hull.vertices[1] = b2Vec2(-1.25, -0.7);
	hull.vertices[2] = b2Vec2(1.25, -0.7);	
	hull.vertexCount = 3;
	hull.density = 1.0f;
	hull.friction = 0.0f;
	hull.restitution = 0.995f;
	hull.userData = this;
	body->CreateShape(&hull);
	updateBoundingRadius(hull);
	
	b2PolygonDef wing1;
	wing1.vertices[0] = b2Vec2(-1.25, -0.7);
	wing1.vertices[1] = b2Vec2(-1.25, -1.1);
	wing1.vertices[2] = b2Vec2(-0.75, -0.7);	
	wing1.vertexCount = 3;
	wing1.density = 0.5f;
	wing1.friction = 0.0f;
	wing1.restitution = 0.995f;
	wing1.userData = this;
	body->CreateShape(&wing1);
	updateBoundingRadius(wing1);
	
	b2PolygonDef wing2;
	wing2.vertices[0] = b2Vec2(1.25, -0.7);
	wing2.vertices[1] = b2Vec2(0.75, -0.7);
	wing2.vertices[2] = b2Vec2(1.25, -1.1);
	wing2.vertexCount = 3;
	wing2.density = 0.5f;
	wing2.friction = 0.0f;
	wing2.restitution = 0.995f;
	wing2.userData = this;
	body->CreateShape(&wing2);
	updateBoundingRadius(wing2);

	body->SetMassFromShapes();
}

Ship::~Ship()
{
}

void Ship::genLists()
{
	// Main ship
	glNewList(baseDisplayList, GL_COMPILE);
	
	glLineWidth(1.5);
	
	//TOP
	//border
	glColor3f(0.0, 0.0, 1.0);
	glBegin(GL_LINE_STRIP);
	glVertex2f(-.1, 1.2);
	glVertex2f(-.2, 1.2);
	glVertex2f(-.3, .8);
	glVertex2f(-.16, 1.16);
	glVertex2f(-.1, 1.16);
	glEnd();
	
	glBegin(GL_LINE_STRIP);
	glVertex2f(0, 1.2);
	glVertex2f(.1, 1.2);
	glVertex2f(.2, .8);
	glVertex2f(.06, 1.16);
	glVertex2f(0, 1.16);
	glEnd();
	
	//window
	glColor3f(.75, .75, .75);
	glBegin(GL_LINES);
	glVertex2f(-.16, 1);
	glVertex2f(-.16, 1.16);
	glEnd();
	
	glBegin(GL_LINES);
	glVertex2f(.06, 1);
	glVertex2f(.06, 1.16);
	glEnd();
	
	//body
	glColor3f(1.0, 1.0, 0.0);
	glBegin(GL_LINE_STRIP);
	glVertex2f(-.1, 1.0);
	glVertex2f(-.16, 1.0);
	glVertex2f(-.3, .8);
	glVertex2f(.2, .8);
	glVertex2f(.06, 1.0);
	glVertex2f(0, 1.0);
	glEnd();
	
	//primary WEAPON
	glColor3f(.3, .3, .3);
	glBegin(GL_LINE_LOOP);
	glVertex2f(-.1, 1.3);
	glVertex2f(0, 1.3);
	glVertex2f(0, .9);
	glVertex2f(-.1, .9);
	glEnd();
	
	
	//MIDDLE
	//body
	glColor3f(1.0, 1.0, 0.0);
	glBegin(GL_LINE_LOOP);
	glVertex2f(-.2, .8);
	glVertex2f(-.4, .8);
	glVertex2f(-.4, 0);
	glVertex2f(-.2, 0);
	glEnd();
	
	glColor3f(1.0, 1.0, 0.0);
	glBegin(GL_LINE_LOOP);
	glVertex2f(.1, .8);
	glVertex2f(.3, .8);
	glVertex2f(.3, 0);
	glVertex2f(.1, 0);
	glEnd();
	
	//wings
	glColor3f(0.0, 0.0, 1.0);
	glBegin(GL_LINE_STRIP);
	glVertex2f(-.4, .5);
	glVertex2f(-.5, .5);
	glVertex2f(-.7, .2);
	glVertex2f(-.4, .2);
	glEnd();
	
	glColor3f(0.0, 0.0, 1.0);
	glBegin(GL_LINE_STRIP);
	glVertex2f(.3, .5);
	glVertex2f(.4, .5);
	glVertex2f(.6, .2);
	glVertex2f(.3, .2);
	glEnd();
	
	
	//BOTTOM
	//body
	glColor3f(1.0, 1.0, 0.0);
	glBegin(GL_LINE_STRIP);
	glVertex2f(-.5, -.2);
	glVertex2f(-.5, 0);
	glVertex2f(.4, 0);
	glVertex2f(.4, -.2);
	glEnd();
	
	glBegin(GL_LINES);
	glVertex2f(-.2, -.5);
	glVertex2f(.1, -.5);
	glEnd();
	
	//burners
	glColor3f(.3, .3, .3);
	glBegin(GL_LINE_LOOP);
	glVertex2f(-.2, -.2);
	glVertex2f(-.6, -.2);
	glVertex2f(-.6, -.7);
	glVertex2f(-.2, -.7);
	glEnd();
	
	glBegin(GL_LINE_LOOP);
	glVertex2f(.1, -.2);
	glVertex2f(.5, -.2);
	glVertex2f(.5, -.7);
	glVertex2f(.1, -.7);
	glEnd();
	
	//back wings
	glColor3f(0.0, 0.0, 1.0);
	glBegin(GL_LINE_STRIP);
	glVertex2f(-.6, -.3);
	glVertex2f(-.9, -.3);
	glVertex2f(-1.2, -.6);
	glVertex2f(-1.3, -1.0);
	glVertex2f(-1.3, -1.3);
	glVertex2f(-.8, -.7);
	glVertex2f(-.6, -.7);
	glEnd();
	
	glBegin(GL_LINE_STRIP);
	glVertex2f(.5, -.3);
	glVertex2f(.8, -.3);
	glVertex2f(1.1, -.6);
	glVertex2f(1.2, -1.0);
	glVertex2f(1.2, -1.3);
	glVertex2f(.7, -.7);
	glVertex2f(.5, -.7);
	glEnd();
	
	glEndList();
	
	// Flames
	glNewList(baseDisplayList + 1, GL_COMPILE);
	
	//FIRE
	//top
	glColor3f(0.0, 0.0, 1.0);
	glBegin(GL_LINE_STRIP);
	glVertex2f(-.6, -.7);
	glVertex2f(-.7, -.8);
	glColor3f(1.0, 1.0, 1.0);
	glVertex2f(-.6, -.9);
	glColor3f(0.0, 0.0, 1.0);
	glVertex2f(-.5, -.8);
	glColor3f(1.0, 1.0, 1.0);
	glVertex2f(-.4, -.9);
	glColor3f(0.0, 0.0, 1.0);
	glVertex2f(-.3, -.8);
	glColor3f(1.0, 1.0, 1.0);
	glVertex2f(-.2, -.9);
	glColor3f(0.0, 0.0, 1.0);
	glVertex2f(-.1, -.8);
	glVertex2f(-.2, -.7);
	glEnd();
	
	glColor3f(0.0, 0.0, 1.0);
	glBegin(GL_LINE_STRIP);
	glVertex2f(.5, -.7);
	glVertex2f(.6, -.8);
	glColor3f(1.0, 1.0, 1.0);
	glVertex2f(.5, -.9);
	glColor3f(0.0, 0.0, 1.0);
	glVertex2f(.4, -.8);
	glColor3f(1.0, 1.0, 1.0);
	glVertex2f(.3, -.9);
	glColor3f(0.0, 0.0, 1.0);
	glVertex2f(.2, -.8);
	glColor3f(1.0, 1.0, 1.0);
	glVertex2f(.1, -.9);
	glColor3f(0.0, 0.0, 1.0);
	glVertex2f(0, -.8);
	glVertex2f(.1, -.7);
	glEnd();
	
	//bottom
	glColor3f(1.0, 1.0, 1.0);
	glBegin(GL_LINE_STRIP);
	glVertex2f(-.6, -.9);
	glColor3f(1.0, .65, 0.0);
	glVertex2f(-.7, -1.2);
	glColor3f(1.0, 0.0, 0.0);
	glVertex2f(-.6, -1.5);
	glColor3f(.7, .13, .13);
	glVertex2f(-.4, -1.7);
	glColor3f(1.0, 0.0, 0.0);
	glVertex2f(-.2, -1.5);
	glColor3f(1.0, .65, 0.0);
	glVertex2f(-.1, -1.2);
	glColor3f(1.0, 1.0, 1.0);
	glVertex2f(-.2, -.9);
	glEnd();
	
	glColor3f(1.0, 1.0, 1.0);
	glBegin(GL_LINE_STRIP);
	glVertex2f(.5, -.9);
	glColor3f(1.0, .65, 0.0);
	glVertex2f(.6, -1.2);
	glColor3f(1.0, 0.0, 0.0);
	glVertex2f(.5, -1.5);
	glColor3f(.7, .13, .13);
	glVertex2f(.3, -1.7);
	glColor3f(1.0, 0.0, 0.0);
	glVertex2f(.1, -1.5);
	glColor3f(1.0, .65, 0.0);
	glVertex2f(0, -1.2);
	glColor3f(1.0, 1.0, 1.0);
	glVertex2f(.1, -.9);
	glEnd();
	
	//detail
	glColor3f(1.0, 1.0, 1.0);
	glBegin(GL_LINE_STRIP);
	glVertex2f(-.5, -.9);
	glColor3f(1.0, .65, 0.0);
	glVertex2f(-.6, -1.2);
	glColor3f(1.0, 0.0, 0.0);
	glVertex2f(-.5, -1.5);
	glEnd();
	
	glColor3f(1.0, 1.0, 1.0);
	glBegin(GL_LINE_STRIP);
	glVertex2f(-.3, -.9);
	glColor3f(1.0, .65, 0.0);
	glVertex2f(-.2, -1.2);
	glColor3f(1.0, 0.0, 0.0);
	glVertex2f(-.3, -1.5);
	glEnd();
	
	glColor3f(1.0, 1.0, 1.0);
	glBegin(GL_LINE_STRIP);
	glVertex2f(.4, -.9);
	glColor3f(1.0, .65, 0.0);
	glVertex2f(.5, -1.2);
	glColor3f(1.0, 0.0, 0.0);
	glVertex2f(.4, -1.5);
	glEnd();
	
	glColor3f(1.0, 1.0, 1.0);
	glBegin(GL_LINE_STRIP);
	glVertex2f(.2, -.9);
	glColor3f(1.0, .65, 0.0);
	glVertex2f(.1, -1.2);
	glColor3f(1.0, 0.0, 0.0);
	glVertex2f(.2, -1.5);
	glEnd();
	
	glEndList();
}

void Ship::draw()
{
	b2Vec2 position = body->GetPosition();
	float32 angle = body->GetAngle();

	glPushMatrix();
	glPushAttrib(GL_COLOR_BUFFER_BIT);
	
	glTranslatef(position.x, position.y, 0.0);
	glRotatef(angle*180.0/M_PI, 0.0, 0.0, 1.0);
	
	glTranslatef(0.05, 0.2, 0.0);
	
	glCallList(baseDisplayList);
	
	if (thrusting)
	{
		glCallList(baseDisplayList + 1);
	}
	
	glPopAttrib();
	glPopMatrix();
}

void Ship::forward()
{
	// TODO: Make this better?
	float32 angle = body->GetAngle();
	
	b2Vec2 force(40.0*cos(angle + M_PI/2.0), 40.0*sin(angle + M_PI/2.0));
	b2Vec2 vel = body->GetLinearVelocity();
	float32 speed = vel.Length();
	
	float32 angleBetween = acos(b2Dot(vel, force) / (force.Length() * speed));
	
	if (speed < Ship::MAX_SPEED || angleBetween >= M_PI/2.0)
	{
		thrusting = true;
		body->ApplyForce(force, body->GetWorldPoint(b2Vec2(0, 0)));
	}
	else
	{
		thrusting = false;
	}
}

void Ship::stopRotation()
{
	body->SetAngularVelocity(0);
}

void Ship::stopThrust()
{
	thrusting = false;
}
